package cn.com.dhcc.turbo.service.registry.sync.webservice;

import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import cn.com.dhcc.app.core.CM;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.exception.NiceException;
import cn.com.dhcc.app.core.exception.ServiceException;
import cn.com.dhcc.app.core.handler.modulehandler.WhereCondition;
import cn.com.dhcc.app.core.service.BaseService;
import cn.com.dhcc.app.core.service.Log;
import cn.com.dhcc.app.core.service.Log.LOGTYPE;
import cn.com.dhcc.app.core.tag.CommonStaticCode.YESNO;
import cn.com.dhcc.app.core.util.CollectionUtil;
import cn.com.dhcc.app.core.util.UrlUtil;
import cn.com.dhcc.app.core.util.WSDLValidatorUtil;
import cn.com.dhcc.app.pub.core.consts.NodeInfoParam;
import cn.com.dhcc.turbo.entity.registry.DomainInfo;
import cn.com.dhcc.turbo.entity.registry.ExchConnRequest;
import cn.com.dhcc.turbo.entity.registry.NodeInfo;
import cn.com.dhcc.turbo.entity.registry.NodePipeline;
import cn.com.dhcc.turbo.entity.registry.NodePipeline.PIPE_TYPE;
import cn.com.dhcc.turbo.entity.registry.SynchronizeInfo;
import cn.com.dhcc.turbo.service.registry.DomainInfoService;
import cn.com.dhcc.turbo.service.registry.NodeInfoService;
import cn.com.dhcc.turbo.service.registry.NodePipelineService;
import cn.com.dhcc.turbo.service.registry.vo.NodeExchRelVo;

/**
 * 
 * @author qiao
 * @2014-5-30 @上午10:01:28
 */
@Service
public class NodeCommunicateService extends BaseService {

	@Autowired
	DomainInfoService domainInfoService;
	@Autowired
	NodeInfoService nodeInfoService;
	
	@Autowired
	NodePipelineService nodePipelineService;
	@SuppressWarnings("deprecation")
	private static Logger logger = Log.getExistLogger(LOGTYPE.SYS);

	/**
	 * 获取本地节点信息
	 * @return
	 * @throws ServiceException
	 */
	public NodeInfo getLocalNodeInfo() throws ServiceException {
		try {
			return nodeInfoService.getLocalNode();
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}

	/**
	 * 获取本地节点信息
	 * @return
	 * @throws ServiceException
	 */
	public NodeInfo getNodeInfo(String id) throws ServiceException {
		try {
			return nodeInfoService.get(id);
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}

	public void insertRemoteNode(NodeInfo remoteNodeInfo) throws ServiceException {
		try {
			nodeInfoService.insertOrUpdateRemoteNode(remoteNodeInfo);
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}

	/**
	 * 获取所有节点
	 * @return
	 * @throws DaoException
	 */
	public List<NodeInfo> getAllNodes() throws ServiceException {
		try {
			return nodeInfoService.getAllNodeList();
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}

	/**
	 * 根据注册节点id获取远程发起的待审核注册请求
	 * @param registNodeId
	 * @return
	 * @throws ServiceException
	 */
	public ExchConnRequest getRemoteWaitAuthRequestByRequestNodeId(String registNodeId) throws ServiceException {
		try {
			WhereCondition searchParameter = new WhereCondition();
			searchParameter.where().eq("islocal", YESNO.NO.getStatus()).and()
					.eq("STATUS", ExchConnRequest.RequestStatus.WAIT.getCode()).and().eq("from_node_id", registNodeId)
					.and().eq("REQUEST_TYPE", ExchConnRequest.RequestType.EXCH_REL.getType());
			return CM.getDao().getModule("获取本地注册请求", ExchConnRequest.class, searchParameter);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}

	public List<NodePipeline> getLocaNodesPipeLines(String localNodeId) throws ServiceException {

		String sql = "select * from " + SI_TABLE("TURBO_NODE_PIPELINE");
		WhereCondition whereCondition = new WhereCondition();
		whereCondition.where().eq("node_id", localNodeId);
		try {
			return CM.getDao().listModule("获取本地节点所有通道信息", sql, NodePipeline.class, whereCondition);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}

	public boolean hasConnectRel(NodeInfo fromNode, NodeInfo localNode) throws ServiceException {
		String sql = "select 1 from " + SI_TABLE("TURBO_EXCH_REL") + " t where t.NODE_ID_CREATOR=? and t.NODE_ID_TO=?";
		try {
			Integer has = CM.getDao().queryForInt("验证节点是已经注册，并且是其他节点的子节点", sql,
					new Object[] { fromNode.getId(), localNode.getId() });
			return has == null ? false : true;
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}

	public void insertOrUpdateRemoteNode(NodeInfo remoteNode) throws ServiceException {
		try {
			nodeInfoService.insertOrUpdateRemoteNode(remoteNode);
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}

	public void insertOrUpdateRemoteDomainNode(DomainInfo domainInfo) throws ServiceException {
		try {
			domainInfoService.insertOrUpdate(domainInfo);
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}

	/*public void deleteRemoteSysInfo(SysInfo sysInfo) throws ServiceException {
		try {
			sysInfoService.deleteRemoteSysInfo(sysInfo);
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}*/

	/*public void insertOrUpdateRemoteSysInfo(SysInfo sysInfo) throws ServiceException {
		try {
			sysInfoService.saveOrUpdateRemoteSysInfo(sysInfo);
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}*/

	public void insertOrUpdateRemotePipeLineInfo(NodePipeline pipeLine) throws ServiceException {
		try {
			nodePipelineService.insertOrUpdateRemotePipeLine(pipeLine);
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}

	public void insertOrUpdateRemotePipeLineInfo(List<NodePipeline> pipeLines) throws ServiceException {
		try {
			if (CollectionUtil.hasElement(pipeLines)) {
				for (Iterator<NodePipeline> iterator = pipeLines.iterator(); iterator.hasNext();) {
					NodePipeline pipeLine = iterator.next();
					insertOrUpdateRemotePipeLineInfo(pipeLine);
				}
			}
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}

	/*public void insertOrUpdateRemoteSysInfo(List<SysInfo> sysInfos) throws ServiceException {
		try {
			if (CollectionUtil.hasElement(sysInfos)) {
				for (Iterator<SysInfo> iterator = sysInfos.iterator(); iterator.hasNext();) {
					SysInfo sysInfo = iterator.next();
					sysInfoService.saveOrUpdateRemoteSysInfo(sysInfo);
				}
			}
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}

	}
*/
	/**
	 * 查询本地发起的待审核请求
	 * @return
	 * @throws ServiceException 
	 */
	public ExchConnRequest getLocalWaitAuthRegistRequest(String url) throws ServiceException {
		try {
			WhereCondition searchParameter = new WhereCondition();
			searchParameter.where().eq("islocal", YESNO.YES.getStatus()).and()
					.eq("STATUS", ExchConnRequest.RequestStatus.WAIT.getCode()).and()
					.eq("REQUEST_TYPE", ExchConnRequest.RequestType.EXCH_REL.getType()).and()
					.eq("TO_URL", url.toLowerCase());
			return CM.getDao().getModule("获取本地注册请求", ExchConnRequest.class, searchParameter);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}

	/**
	 * 验证同步地址是否可用 必须在项目启动后才能验证。
	 * @param installUrl
	 * @return
	 */
	public boolean syncUrlIsValid(String installUrl) {
		installUrl = UrlUtil.removeSlashAndBlack(installUrl);
		try {
			return WSDLValidatorUtil.validate(installUrl + NodeInfoParam.SYNC_WSDL_SURFIX);
		} catch (Exception e) {
			return false;
		}
	}

	public boolean hasRequestAndWaitAuth(NodeInfo registNode) throws ServiceException {
		try {
			ExchConnRequest connRequest = getRemoteWaitAuthRequestByRequestNodeId(registNode.getId());
			return connRequest != null;
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}

	/*public List<SysInfo> getLocaNodesSysInfos(String nodeId) throws ServiceException {
		String sql = "select * from " + SI_TABLE("TURBO_SYS_INFO");
		WhereCondition whereCondition = new WhereCondition();
		whereCondition.where().eq("node_id", nodeId);
		try {
			return CM.getDao().listModule("获取本地节点所有已注册系统信息", sql, SysInfo.class, whereCondition);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}*/

	public NodeExchRelVo getlocalNeedSyncInfo() throws NiceException {
		NodeExchRelVo connRequest = new NodeExchRelVo();
		try {
			NodeInfo localNode = getLocalNodeInfo();
			List<NodePipeline> pipeLines = getLocaNodesPipeLines(localNode.getId());
			//List<SysInfo> sysInfos = getLocaNodesSysInfos(localNode.getId());
			List<DomainInfo> domainInfos = domainInfoService.list(null);
			connRequest.setFromNode(localNode);
			connRequest.setPipeLines(pipeLines);
			//connRequest.setSysInfos(sysInfos);
			connRequest.setDomainInfos(domainInfos);
		} catch (Exception e) {
			throw new NiceException("获取节点信息失败", e);
		}
		return connRequest;
	}

	public void insertExchRel(NodeInfo creatorNode, NodeInfo toNode) throws NiceException {

		String sql = " insert into " + SI_TABLE("TURBO_EXCH_REL") + " (NODE_ID_CREATOR,NODE_ID_TO,MTIME) values('"
				+ creatorNode.getId() + "','" + toNode.getId() + "',sysdate)";
		try {
			CM.getDao().insert("插入交换关系", sql, new Object[] {});
		} catch (DaoException e) {
			throw new NiceException("插入交换关失败", e);
		}
	}

	public ExchConnRequest getExchRequest(String exchConnRequestId) throws ServiceException {
		try {
			return CM.getDao().getModuleById("获取交换关系请求信息", ExchConnRequest.class, new Object[] { exchConnRequestId });
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}

	/**
	 * 获取有交换关系的节点信息
	 * @return
	 * @throws ServiceException
	 */
	public List<NodeInfo> getHasRelNodes() throws ServiceException {
		String sql = "select *  from " + SI_TABLE("TURBO_NODE_INFO") + " n where n.STATUS=1";
		try {
			WhereCondition whereCondition = new WhereCondition();
			whereCondition.and().eq("islocal", YESNO.NO.getStatus());
			return CM.getDao().listModule("获取有交换关系的节点", sql, NodeInfo.class, whereCondition);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}

	public void insertOrUpdateSynchronizeInfo(SynchronizeInfo synchronizeInfo) throws ServiceException {
		try {
			CM.getDao().saveOrUpdateModuleById("插入或修改同步信息", synchronizeInfo, null);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}

	public void insertOrUpdateRemoteDomains(List<DomainInfo> domainInfos) throws ServiceException {
		try {
			if (CollectionUtil.hasElement(domainInfos)) {
				for (Iterator<DomainInfo> iterator = domainInfos.iterator(); iterator.hasNext();) {
					DomainInfo domainInfo = iterator.next();
					insertOrUpdateRemoteDomainNode(domainInfo);
				}
			}
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
	}

	public void insertOrUpdateConnRequest(ExchConnRequest connRequest) throws ServiceException {
		try {
			CM.getDao().saveOrUpdateModuleByIdExecuteNull("插入或者修改注册请求，状态为->" + connRequest.getStatus(), connRequest);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}

	public void checkLocalPipeLine(List<NodePipeline> nodePipelines) throws NiceException {
		if (!CollectionUtil.hasElement(nodePipelines)) {
			throw new NiceException("请求验证失败,本地节点通道未初始化！");
		}
		boolean ftpCheckPass = false;
		boolean tlqCheckPass = true;
		for (Iterator<NodePipeline> iterator = nodePipelines.iterator(); iterator.hasNext();) {
			NodePipeline nodePipeline = iterator.next();
			if (PIPE_TYPE.FTP_EMBED.getCode().equalsIgnoreCase(nodePipeline.getPipeType())) {
				ftpCheckPass = true;
			} else if (PIPE_TYPE.TONGLINKQ.getCode().equalsIgnoreCase(nodePipeline.getPipeType())) {
				tlqCheckPass = true;
			} else {
				//other not support
			}
		}
		if (!ftpCheckPass) {
			throw new NiceException("请求验证失败,本地节点FTP未初始化！");
		}
		if (!tlqCheckPass) {
			throw new NiceException("请求验证失败,本地节点TongLinkQ未初始化！");
		}
	}

	/**
	 * 验证网络类型是否一致
	 * @param fromNode
	 * @param localNode
	 * @return
	 */
	public boolean ifNetDomainSame(NodeInfo fromNode, NodeInfo localNode) {
		return fromNode.getNetTypeCode().equals(localNode.getNetTypeCode());
	}

	public String getSyncWsUrl(String nodeInstallUrl) {
		if (StringUtils.hasText(nodeInstallUrl)) {
			if (nodeInstallUrl.trim().endsWith("/")) {
				nodeInstallUrl = nodeInstallUrl.substring(0, nodeInstallUrl.length() - 1);
				return getSyncWsUrl(nodeInstallUrl);
			} else {
				return nodeInstallUrl;
			}
		}
		return "";
	}

	public boolean isSelfUrl(String nodeInstallUrl) {
		nodeInstallUrl = UrlUtil.removeSlashAndBlack(nodeInstallUrl);
		return false;//nodeInstallUrl.toLowerCase().indexOf(NodeInfoParam.APP_SERVER_URL) != -1;
	}

	public static String getSyncUrl(String installUrl) {
		return UrlUtil.removeSlashAndBlack(installUrl) + NodeInfoParam.SYNC_WSDL_SURFIX;
	}

	public void updateRequestStatus(ExchConnRequest connRequestLocal, ExchConnRequest.RequestStatus status, String msg) {
		connRequestLocal.setStatus(status.getCode());
		connRequestLocal.setResponse(msg);
		try {
			CM.getDao().updateModuleById("修改注册请求状态为->" + connRequestLocal.getStatus(), connRequestLocal, null);
		} catch (DaoException e) {
			logger.error("修改状态失败..", e);
		}
	}

	public boolean hasExchRel(String fromNodeId, String toNodeId) throws ServiceException {
		try {
			NodeInfo from = nodeInfoService.get(fromNodeId);
			NodeInfo to = nodeInfoService.get(toNodeId);
			if (from != null && to != null) {
				return true;
			}
		} catch (ServiceException e) {
			throw e;
		}
		return false;
	}
}
